package com.jts.cloudspokes;

import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.JDODataStoreException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.appengine.api.labs.taskqueue.TaskOptions;
import com.google.appengine.api.labs.taskqueue.TaskOptions.Method;
import com.google.appengine.api.xmpp.Message;
import com.google.appengine.api.xmpp.MessageBuilder;
import com.google.appengine.api.xmpp.MessageType;
import com.google.appengine.api.xmpp.XMPPService;
import com.google.appengine.api.xmpp.XMPPServiceFactory;
import com.jts.cloudspokes.datastore.BotDSManager;
import com.jts.cloudspokes.entities.BotTaskEntity;
import com.jts.cloudspokes.util.BotUtility;

@SuppressWarnings("serial")
public class BotServlet extends HttpServlet {
	private static final XMPPService xmppService = XMPPServiceFactory.getXMPPService();
	private static final Logger logger = Logger.getLogger(BotServlet.class.getName());
	private static final BotDSManager botDSManager = new BotDSManager();
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		logger.info("Message Received");
		Message message = xmppService.parseMessage(req);
		String response = processUserInput(message);
		Message reply =  new MessageBuilder()
		.withRecipientJids(message.getFromJid())
		.withMessageType(MessageType.NORMAL)
		.withBody(response)
		.build();
		xmppService.sendMessage(reply);		
	 }
	
	@SuppressWarnings("finally")
	private String processUserInput(Message message) {
		String userInput = message.getBody();
		String userId = message.getFromJid().getId();
		String processUserInput = userInput.trim().toUpperCase().replaceAll(" ", "");
		logger.warning("Input: " + processUserInput + " " + processUserInput.length());
		String output = BotConstants.HELP_TEXT;
		botDSManager.startPersistenceManager();
		try {
			if (processUserInput.equals(BotConstants.CMD_FETCH)) {
				output = fetchAllTasks(userId);
			} else if (processUserInput.equals(BotConstants.CMD_DELETE_ALL)) {
				output = botDSManager.deleteAllTasks(userId);
			} else if (processUserInput.startsWith(BotConstants.CMD_DELETE)) {				
				output = botDSManager.deleteTask(userId, processUserInput.replace(BotConstants.CMD_DELETE, ""));
			} else if (processUserInput.equals(BotConstants.CMD_HELP)) {
				output = BotConstants.HELP_TEXT;
			} else {
				output = createTask(message);
			}
		} finally {
			botDSManager.stopPersistenceManager();
			return output;
		}		
	}
	
	@SuppressWarnings("finally")
	private String fetchAllTasks(String userId) {
		logger.warning("Going to fetch tasks");
		String response = "Created tasks are:";
		try {
			List<BotTaskEntity> taskEntities = botDSManager.fetchTasksFromDS(userId);
			if (taskEntities == null || taskEntities.isEmpty()) {
				response = "No tasks available";
			} else {
				for (BotTaskEntity taskEntity : taskEntities) {
					response += "\n" + taskEntity.getKey() + " - " + taskEntity.getTaskMessage()
					+ " is due in " + BotUtility.getDueTime(taskEntity.getTaskDate(), taskEntity.getCountDownMs());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			response = "Error: Not able to fetch tasks";
		} finally {
			return response;
		}		
	}
	
	@SuppressWarnings("finally")
	private String createTask(Message message) {
		String response =  BotConstants.STATUS_TASK_CREATED;
		BotTaskEntity bteObj = BotUtility.createBotTaskEntityFromMessage(message);
		if (bteObj == null) {
			response = BotConstants.HELP_TEXT;
			return response;
		}
		
		try {
			botDSManager.getPersistentManager().makePersistent(bteObj);
			Queue queue = QueueFactory.getDefaultQueue();
			queue.add(TaskOptions.Builder.url("/taskDelivery")
					.param(BotConstants.PARAM_TASK_ID, bteObj.getKey() + "")
					.method(Method.POST)
					.countdownMillis(bteObj.getCountDownMs()));
			logger.info("Task " + bteObj.getKey() + " added to Queue");
		} catch (JDODataStoreException e) {
			e.printStackTrace();
			response = "Error: Not able to create task";
			logger.warning("Error: task was not created " + e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			response = "Error: Not able to create/add task. " + e.getMessage();
			logger.log(Level.SEVERE, "Error: task was not added/created" + e.getMessage());
		} finally {
			return response;
		}
	}	
	
}
